//
//  YYFileMiddleware.swift
//  App
//
//  Created by yuany on 2020/1/14.
//

import Foundation
import SwiftMarkdown
import Vapor

public final class YYFileMiddleware: Middleware {
    /// Must end with a slash.
    private let publicDirectory: String
    
    /// Creates a new `FileMiddleware`.
    public init(publicDirectory: String) {
        self.publicDirectory = publicDirectory.hasSuffix("/") ? publicDirectory : publicDirectory + "/"
    }
    
    public func respond(to request: Request, chainingTo next: Responder) -> EventLoopFuture<Response> {
        var path = request.url.path
        
        // path must be relative.
        while path.hasPrefix("/") {
            path = String(path.dropFirst())
        }
        
        guard !path.contains("../") else {
            return request.eventLoop.makeFailedFuture(Abort(.forbidden))
        }
        
        let filePath = publicDirectory + path.urlDecoded()
        var isDir: ObjCBool = false
        guard FileManager.default.fileExists(atPath: filePath, isDirectory: &isDir), !isDir.boolValue else {
            return next.respond(to: request)
        }
        
        if path.pathExtension == "md" {
            return FileManager.default.contents(atPath: filePath)
                .flatMap { String(data: $0, encoding: .utf8) }
                .flatMap { try? markdownToHTML($0) }
                .map { str -> Response in
                    let res = Response(status: .ok, body: Response.Body(string: str))
                    res.headers.contentType = .html
                    return res
                }?
                .encodeResponse(for: request)
                ??
                request.fileio.streamFile(at: filePath).encodeResponse(for: request)
        }
        
        return request.fileio.streamFile(at: filePath).encodeResponse(for: request)
    }
}
